#ifndef CLASSBROWSERBUILDERTHREAD_H
#define CLASSBROWSERBUILDERTHREAD_H

#include <wx/thread.h>
#include <wx/treectrl.h>

#include "cctreectrl.h"
#include "nativeparser.h"
#include "parser/token.h"
#include "parser/parser.h"


class ClassBrowserBuilderThread : public wxThread {
  public:
    enum EThreadEvent {
      selectItemRequired,
      buildTreeStart,
      buildTreeEnd
    };
    ClassBrowserBuilderThread( wxEvtHandler* evtHandler, wxSemaphore& sem );
    virtual ~ClassBrowserBuilderThread();
    void Init( NativeParser* np, CCTreeCtrl* treeTop, CCTreeCtrl* treeBottom,
               const wxString& active_filename, void* user_data,
               const BrowserOptions& bo, TokenTree* tt,
               int idThreadEvent );
    void ExpandItem( wxTreeItemId item );
    void CollapseItem( wxTreeItemId item );
    void SelectItem( wxTreeItemId item );
    void SelectItemRequired();
    void RequestTermination( bool terminate = true ) { m_TerminationRequested = terminate; }
  protected:
    virtual void* Entry();
    void BuildTree();
    void RemoveInvalidNodes( CCTreeCtrl* tree, wxTreeItemId parent );
    void ExpandNamespaces( wxTreeItemId node, TokenKind tokenKind, int level );
    bool CreateSpecialFolders( CCTreeCtrl* tree, wxTreeItemId parent );
    wxTreeItemId AddNodeIfNotThere( CCTreeCtrl* tree, wxTreeItemId parent,
                                    const wxString& name, int imgIndex = -1, CCTreeCtrlData* data = 0 );
    bool AddChildrenOf( CCTreeCtrl* tree, wxTreeItemId parent, int parentTokenIdx,
                        short int tokenKindMask = 0xffff, int tokenScopeMask = 0 );
    bool AddAncestorsOf( CCTreeCtrl* tree, wxTreeItemId parent, int tokenIdx );
    bool AddDescendantsOf( CCTreeCtrl* tree, wxTreeItemId parent, int tokenIdx, bool allowInheritance = true );
    void AddMembersOf( CCTreeCtrl* tree, wxTreeItemId node );
  private:
    bool AddNodes( CCTreeCtrl* tree, wxTreeItemId parent, const TokenIdxSet* tokens,
                   short int tokenKindMask = 0xffff, int tokenScopeMask = 0, bool allowGlobals = false );
    bool TokenMatchesFilter( const Token* token, bool locked = false );
    bool TokenContainsChildrenOfKind( const Token* token, int kind );
    void SaveExpandedItems( CCTreeCtrl* tree, wxTreeItemId parent, int level );
    void ExpandSavedItems( CCTreeCtrl* tree, wxTreeItemId parent, int level );
    void SaveSelectedItem();
    void SelectSavedItem();
  protected:
    wxEvtHandler*    m_Parent;
    wxSemaphore&     m_ClassBrowserSemaphore;
    wxMutex          m_ClassBrowserBuilderThreadMutex;
    NativeParser*    m_NativeParser;
    CCTreeCtrl*      m_CCTreeCtrlTop;
    CCTreeCtrl*      m_CCTreeCtrlBottom;
    wxString         m_ActiveFilename;
    void*            m_UserData;
    BrowserOptions   m_BrowserOptions;
    TokenTree*       m_TokenTree;
    TokenFileSet     m_CurrentFileSet;
    TokenIdxSet      m_CurrentTokenSet;
    TokenIdxSet      m_CurrentGlobalTokensSet;
  private:
    ExpandedItemVect m_ExpandedVect;
    SelectedItemPath m_SelectedPath;
    bool             m_InitDone;
    bool             m_TerminationRequested;
    int              m_idThreadEvent;
    wxTreeItemId     m_SelectItemRequired;
};

#endif
